package com.zjq.authoritysystem.controller.user;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zjq.authoritysystem.config.redis.Cache;
import com.zjq.authoritysystem.entity.Permission;
import com.zjq.authoritysystem.entity.User;
import com.zjq.authoritysystem.service.UserService;
import com.zjq.authoritysystem.utils.BcryptUtil;
import com.zjq.authoritysystem.utils.JwtUtil;
import com.zjq.authoritysystem.utils.MenuTreeUtil;
import com.zjq.authoritysystem.vo.RouteVo;
import com.zjq.authoritysystem.vo.TokenVo;
import com.zjq.authoritysystem.vo.UserInfoVo;
import com.zjq.authoritysystem.vo.query.UserQueryVo;
import com.zjq.authoritysystem.vo.result.Result;
import io.jsonwebtoken.Jwts;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Kimiaaaaa
 * @className UserController
 * @Description
 * @date 2023-09-19 14:40
 */
@Slf4j
@Api(tags = "用户控制器")
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private Cache cache;


    @ApiOperation(value = "获取用户信息", notes = "获取")
    @GetMapping("/getInfo")
    public Result getInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            return Result.Error("查询用户信息失败");
        }
        User user = (User) authentication.getPrincipal();
        List<Permission> permissionList = user.getPermissionList();
        //获取角色权限编码字段
        Object[] roles = permissionList.stream().filter(Objects::nonNull)
                .map(Permission::getCode).toArray();
        //创建用户信息对象
        UserInfoVo userInfoVo = new UserInfoVo(user.getId(), user.getNickName(), user.getAvatar(), null, roles);
        return Result.SUCCESS(userInfoVo);
    }

    @ApiOperation(value = "获取登录用户的菜单数据", notes = "获取登录用户的菜单权限列表")
    @GetMapping("/getMenuList")
    public Result getMenuList() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = (User) authentication.getPrincipal();

        List<Permission> permissionList = user.getPermissionList();
        List<Permission> permissions = permissionList.stream()
                //筛选目录和菜单数据
                .filter(permission -> permission != null && permission.getType() != Permission.TYPE_BUTTON)
                .collect(Collectors.toList());

        //生成路由信息
        List<RouteVo> routeVos = MenuTreeUtil.makeRoute(permissions, Permission.PARENT_MENU_ID);
        return Result.SUCCESS(routeVos);
    }

    @ApiOperation(value = "退出登录", notes = "用户退出登录")
    @PostMapping("/logout")
    public Result logout(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("token");
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 判断用户信息是否为空，不为空则需要清空用户信息
        if (authentication != null) {
            // 清除security中的用户信息
            new SecurityContextLogoutHandler().logout(request, response, authentication);

            // 清除redis缓存中的token
            cache.remove("token_" + token);
            return Result.SUCCESS("退出成功");
        }
        return Result.Error("退出失败");
    }

    @ApiOperation(value = "刷新token信息", notes = "刷新token信息")
    @PostMapping("/refreshToken")
    public Result refreshToken(HttpServletRequest request) {
        String token = request.getHeader("token");
        //从上下文获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        //获取用户身份信息
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();

        //验证旧token、生成新token、清除旧token、保存新token
        String newToken = "";
        Boolean validateToken = jwtUtil.validateToken(token, userDetails);
        if (validateToken) {
            newToken = jwtUtil.refreshToken(token);
        }

        long expireTime = Jwts.parser()
                .setSigningKey(jwtUtil.getSignatureKey())
                .parseClaimsJws(newToken.replace("jwt", ""))
                .getBody()
                .getExpiration().getTime();

        String oldTokenRedisKey = "token_" + token;
        String newTokenRedisKey = "token_" + newToken;

        cache.remove(oldTokenRedisKey);
        cache.put(newTokenRedisKey, newToken, jwtUtil.getExpire());
        TokenVo tokenVo = new TokenVo(expireTime, newToken);
        Result result = Result.SUCCESS(tokenVo);
        result.setMsg("token刷新成功");
        return result;
    }


    @ApiOperation(value = "分页查询用户列表")
    @PostMapping("/list")
    public Result list(@RequestBody UserQueryVo userQueryVo) {
        IPage iPage = userService.findPages(userQueryVo);
        return Result.SUCCESS(iPage);
    }

    @ApiOperation(value = "保存用户信息")
    @PostMapping("/save")
    public Result save(@RequestBody User user) {
        // 检查数据信息
        checkUserData(user);
        User byUsername = userService.getByUsername(user.getUsername());
        if (user.getId() == null && byUsername != null) {
            return Result.Error("该用户名已经被占用");
        }
        // 密码加密
        user.setPassword(BcryptUtil.passwordEncryption(user.getPassword()));
        boolean update = userService.saveOrUpdate(user);
        if (!update) {
            return Result.Error("操作失败，请检查数据信息");
        }
        return Result.SUCCESS();
    }

    @ApiOperation(value = "删除用户信息")
    @PostMapping("/delete/{id}")
    public Result delete(@PathVariable Integer id) {
        boolean delete = userService.deleteById(id);
        if (!delete) {
            return Result.Error("操作失败，请检查数据信息");
        }
        return Result.SUCCESS();
    }

    @ApiOperation(value = "根据用户编号获取用户信息")
    @GetMapping("/get/{id}")
    public Result get(@PathVariable Integer id) {
        User user = userService.getById(id);
        return Result.SUCCESS(user);
    }

    /**
     * 检查用户信息中的数据
     *
     * @param user 用户信息
     */
    private void checkUserData(User user) {
        if (user.getIsAdmin() == null) {
            user.setIsAdmin(User.IS_ADMIN_NO);
        }
        if (user.getAvatar() == null) {
            user.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        }
    }
}
